/*
2011-06-17
 1. 增加 getMeRow(DatabaseAdapter, Object) method.

2009-11-19
 1. 增加 getMaximin method : 方便取得 Table 某欄位的最大或最小值。
 2. 增加 DatabaseAdapter 架構：實作 getConnection(), freeConnection(Connection)，和增加 setJDBCURL(String)。
 3. 增加 truncateTable(), query() method。
*/

package idv.jieh.commons.sql;

import java.sql.*;
import java.util.*;
import idv.jieh.commons.util.*;
import idv.jieh.commons.comm.BasicClass;

public class SimpleConnection extends BasicClass implements DatabaseAdapter {

  private int getcount = 0;
  private int trynum = 1;
  private long waittime = 500L;

  private String jdbcUrl;

  private DeBuger dbr = null;
  private java.util.Properties prop = new java.util.Properties();

  /**
   * 建構子。<p>
   * 設定 Debug 需要的資訊。
   */
  public SimpleConnection() {
    dbr = new DeBuger("SimpleConnection");
  }


  /**
   * 簡單給個 Table Name 就回一個含有該 Table Scheme RowCache，可以當作塞資料的命名化物件。
   * @param c Connection Object。
   * @param t Object : Table Name
   * @return RowCache
   * @throws SQLException
   */
  public static RowCache getMeRow(Connection c, Object t)
  throws java.sql.SQLException{
    SQLMaker sm = new SQLMaker();
    sm.append("select * from ").append(t);
    TableCache tc = new TableCache();
    sm.generateTableCache(c, tc);
    return tc.forInsert();
  }


  /**
   * 簡單給個 Table Name 就回一個含有該 Table Scheme RowCache，可以當作塞資料的命名化物件。
   * @param da DatabaseAdapter Object。
   * @param t Object : Table Name。
   * @return RowCache
   * @throws SQLException
   */
  public static RowCache getMeRow(DatabaseAdapter da, Object t)
    throws java.sql.SQLException
  {
    RowCache r = null;
    Connection c = da.getConnection();
    try{
      r = getMeRow(c, t);
    }catch(SQLException e){
      throw e;
    }finally{
      da.freeConnection(c);
    }
    return r;
  }


  // 2006-02-09 by jieh
  /**
   * 取得資料來源中的第一筆且第一欄的資料。
   * @param da DatabaseAdapter
   * @param sm SQLMaker
   * @return String
   * @throws SQLException
   */
  public static String getData(DatabaseAdapter da, SQLMaker sm)
  throws java.sql.SQLException{
    String r = null;
    Connection c = da.getConnection();
    try{
      r = getData(c, sm);
    }catch(SQLException e){
      throw e;
    }finally{
      da.freeConnection(c);
    }
    return r;
  }

  // 2006-02-09 by jieh
  /**
   * 取得資料來源中的第一筆且第一欄的資料。
   * @param conn Connection
   * @param sm SQLMaker
   * @return String
   * @throws SQLException
   */
  public static String getData(Connection conn, SQLMaker sm)
  throws java.sql.SQLException{
    TableCache tc = new TableCache();
    sm.generateTableCache(conn, tc);
    if(tc.size() >= 1){
      RowCache row = tc.getRow(1);
      return row.elementAt(0).toString();
    }
    return null;
  }

  /**
   * 將 ResultSet 中欄位名稱轉成 Vector 。<p>
   * 如果 JDBC 版本允許的話，會將這個 table 的欄位抓取出來，並以陣列存放後回傳。<p>
   * <font color=red>建議使用 <code>TableCache</code> 類別中的 <u>getAllCols()</u></font> 。
   * @param rs ResultSet 一個有效的資料結果集物件。
   * @throws SQLException 若失敗，將會丟出 Exception
   * @return Vector 欄位名稱 Vector。
   */
  public static Vector getColumn(ResultSet rs) throws SQLException{
    // ADD 20040625 JIEH FOR DEBUG
    if(rs == null) throw new SQLException("DEBUG NULLPOINTEXCEPTION!!! FOR RESULTESET...");
    ResultSetMetaData rsmd = rs.getMetaData();
    // ADD 20040625 JIEH FOR DEBUG
    if(rsmd == null) throw new SQLException("DEBUG NULLPOINTEXCEPTION!!! FOR RESULTESET...");

    int l = rsmd.getColumnCount();
    Vector r = new Vector(l);
    for(int i=1; i<=l; i++){
      r.addElement(rsmd.getColumnName(i).trim().toUpperCase());
    }
    r.trimToSize();
    return r;
  }

  /**
   * 計算筆數。<p>
   * 輸入 Table Name、還有條件值，並且給一個可以使用的 <code>Connection</code>，<br>
   * 這個方法會將查詢到的筆數回傳。
   * @param conn 資料庫連線資源。
   * @param table 資料庫檔案名稱。
   * @param condition 查詢條件，如果無給 null。
   * @return int 查詢結果資料筆數。
   * @throws SQLException
   */
  public static int count(Connection conn, Object table, StringBuilder condition)
    throws SQLException{
    SQLMaker sm = new SQLMaker();
    sm.append("SELECT COUNT(*) AS JIEHCOUNT FROM ").append(table);
    if(condition != null && condition.length() > 0){
      sm.append(" WHERE ").append(condition);
    }

    TableCache tc = new TableCache();
    sm.generateTableCache(conn, tc);
    RowCache row = tc.getRow(1);
    return Integer.parseInt(row.getValue("JIEHCOUNT"));
  }

  // 2009-11-19 by jieh
  /**
   * 查詢最大或最小值。
   * @param da DatabaseAdapter
   * @param columnName String 欄位名稱。
   * @param tableName String 資料表名稱。
   * @param maximin String 最大 MAX 或 最小 MIN。
   * @param condition StringBuilder SQL 條件，如傳入 null 則會忽略。
   * @return String 查詢結果。
   * @throws SQLException
   */
  public static String getMaximin(
    DatabaseAdapter da,
    Object columnName,
    Object tableName,
    String maximin,
    StringBuilder condition
  ) throws SQLException {
    SQLMaker sm = new SQLMaker();
    sm.append("select ").append(maximin).append("(").append(columnName).append(") from ").append(tableName);
    if(condition != null && condition.length() > 0)
      sm.append(" where ").append(condition);
    return getData(da, sm);
  }

  // 2009-11-19 by jieh
  public static int truncateTable(DatabaseAdapter da, Object tableName)
    throws SQLException {
    SQLMaker sm = new SQLMaker();
    sm.append("truncate table ").append(tableName);
    return sm.excuteModify(da);
  }

  // 2009-11-19 by jieh
  public static TableCache query(DatabaseAdapter da, Object tableName)
    throws SQLException {
    TableCache tc = new TableCache();
    SQLMaker sm = new SQLMaker();
    sm.append("select * from ").append(tableName);
    sm.generateTableCache(da, tc);
    return tc;
  }

  /**
   * Register JDBC Driver
   * @param path JDBC Driver Full Class Path.
   * @return boolean true：執行成功；false：失敗。
   */
  public static boolean registerDriver(String path) {
    try {
      Driver driver = (Driver) Class.forName(path).newInstance();
      DriverManager.registerDriver(driver);
      return true;
    } catch(SQLException e){
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return false;
  }

  /**
   * 設定一組 Property。<p>
   * 包含 key 和對應的 value。用於取得連線時的參數。<br>
   * @param key key 值
   * @param value 對應 Key 的值
   */
  public void setProperty(String key, String value){
    prop.setProperty(key, value);
  }

  /**
   * 若成功，將取得一個連線；若失敗將會產生 Connected Fail 的訊息。
   * @param url 資料庫的路徑
   * @return 一個 Connection 物件
   */
  public Connection getConnection(String url){
    Connection c = null;
    try {
      c = DriverManager.getConnection(url, prop);
    } catch(SQLException se){
      dbr.exception(se);
    } catch (Exception e) {
      dbr.exception(e);
    }
    return c;
  }

  /**
   * 切換資料庫連線的資料庫。
   * @param conn Connection
   * @param database String 資料庫名稱。
   * @return boolean true：切換成功；false：切換失敗。
   * @throws SQLException
   */
  public static boolean useDatabase(Connection conn, String database)
    throws SQLException
  {
    return conn.createStatement().execute("use " + database);
  }

  /**
   * 判斷指定的連線物件是否仍有效。
   * @param conn Connection 連線物件。
   * @return boolean true：有效；false：異常。
   */
  public static boolean isAlive(Connection conn){
    try{
      if(conn.isClosed()) return false;
    }catch(Exception e){
      return false;
    }
    return true;
  }

  /**
   * 關閉資料庫連線物件。
   * @param conn 要關閉的資料庫連線物件。
   * @return true：關閉成功；false：關閉失敗。
   */
  public static boolean close(Connection conn){
    if(conn != null){
      try{
        conn.close();
      }catch(SQLException ex){return false;}
      conn = null;
    }
    return true;
  }

  // 2009-11-19 by jieh
  public void setJdbcUrl(String jdbcUrl){
    this.jdbcUrl = jdbcUrl;
  }

  // 2009-11-19 by jieh
  public Connection getConnection(){
    return getConnection(jdbcUrl);
  }

  // 2009-11-19 by jieh
  public boolean freeConnection(Connection conn){
    return close(conn);
  }

  public static void main(String... args) throws Exception{
//    OracleDataSource ods = new OracleDataSource();
//    ods.setUser("ret08report");
//    ods.setPassword("ret08report");
//    ods.setURL("jdbc:oracle:thin:@172.23.5.211:1521:RPT");
//    Connection oracle_conn = ods.getConnection();

    TableCache tc = new TableCache();
    SQLMaker sm = new SQLMaker();
    sm.append("select * from ACH_SEND_MESSAGES");
//    sm.generateTableCache(oracle_conn, tc);
    tc.list();

    SimpleConnection sc = new SimpleConnection();
    sc.setProperty("user", "sa");
    sc.setProperty("password", "muchjavawebsvr");
    Connection conn = sc.getConnection("jdbc:jtds:sqlserver://172.17.113.218:1433/");
  }

}// end class SimpleConnection

